#include "vpdemuxthread.h"
#include <QDebug>
#include "vpentrance.h"
VpDemuxThread::VpDemuxThread()
{
    m_stop = false;
    m_seek_req = false;
}

bool VpDemuxThread::start(AVFormatContext *fmt_ctx, int audio_stream_idx, int video_stream_idx, VpPacketQueue *audio_pkt_queue, VpPacketQueue *video_pkt_queue, int *serial)
{
    m_stop   = false;
    m_seek_req = false;
    bool res = true;
    if(!fmt_ctx)
        res  = false;
    thread demux_th(work, this, fmt_ctx, audio_stream_idx, video_stream_idx, audio_pkt_queue, video_pkt_queue, serial);
    demux_th.detach();
    return res;
}

void VpDemuxThread::stop()
{
    m_stop     = true;
}

void VpDemuxThread::work(VpDemuxThread* vp_demux_th, AVFormatContext *fmt_ctx, int audio_stream_idx, int video_stream_idx, VpPacketQueue *audio_pkt_queue, VpPacketQueue *video_pkt_queue, int *serial)
{
    qDebug()<<"demux thread start";
    VpEntrance::s_RUNNING_THREAD_NUM += 1;
    int ret                           = -1;
    AVRational tbq                    = {1, AV_TIME_BASE};
    while(!vp_demux_th->m_stop)
    {
        VpPacket pkt;
        if(vp_demux_th->m_seek_req) {
            vp_demux_th->m_seek_req        = false;
            int64_t target_pts = vp_demux_th->m_seek_time * AV_TIME_BASE;
//            int64_t target_audio_timestamp = av_rescale_q(target_pts, tbq, fmt_ctx->streams[audio_stream_idx]->time_base);/*vp_demux_th->m_seek_time / av_q2d(fmt_ctx->streams[audio_stream_idx]->time_base);*/
//            int64_t target_video_timestamp = av_rescale_q(target_pts, tbq, fmt_ctx->streams[video_stream_idx]->time_base);
//            av_seek_frame(fmt_ctx, audio_stream_idx, target_audio_timestamp, AVSEEK_FLAG_BACKWARD);
//            av_seek_frame(fmt_ctx, video_stream_idx, target_video_timestamp, AVSEEK_FLAG_BACKWARD);
            avformat_seek_file(fmt_ctx, -1, INT64_MIN, target_pts, INT64_MAX, 0);
            audio_pkt_queue->flush_queue();
            video_pkt_queue->flush_queue();
            avcodec_flush_buffers(audio_pkt_queue->m_codec_ctx);
            avcodec_flush_buffers(video_pkt_queue->m_codec_ctx);
        }
        {
            unique_lock<mutex> lock(vp_demux_th->m_mutex);
            while (video_pkt_queue->get_size() + audio_pkt_queue->get_size() >= MAX_QUEUE_SIZE && !vp_demux_th->m_stop) {
                vp_demux_th->m_cond.wait_for(lock, chrono::milliseconds(10));
            }
        }
        ret = av_read_frame(fmt_ctx, pkt.m_packet);
        if (ret == 0) {
            // 成功读取一帧数据，进行后续处理
            if(pkt.m_packet->stream_index == video_stream_idx)
            {
                pkt.setSerial(*serial);
                video_pkt_queue->push(pkt);
                video_pkt_queue->m_cond.notify_one();
            }
            else if(pkt.m_packet->stream_index == audio_stream_idx)
            {
                pkt.setSerial(*serial);
                audio_pkt_queue->push(pkt);
                audio_pkt_queue->m_cond.notify_one();
            }
        } else if (ret == AVERROR_EOF) {
            // 已经到达文件末尾
            qDebug()<<"video end";
            pkt.setSerial(*serial);
            video_pkt_queue->push(pkt);
            audio_pkt_queue->push(pkt);
            av_usleep(50 * 1000);
        } else {
            // 发生错误，打印错误信息并进行相应处理
            char errbuf[1024];
            av_strerror(ret, errbuf, sizeof(errbuf));
            qDebug() << "av_read_frame error" << errbuf;
            // 根据具体情况进行处理，例如跳过当前帧或结束循环
        }
    }

    {
        lock_guard<mutex> lock(vp_demux_th->m_mutex);
        VpEntrance::s_RUNNING_THREAD_NUM -= 1;
        qDebug()<<"demux thread end";
    }
    return;
}

void VpDemuxThread::seek_time(int seek_time)
{
    m_seek_req  = true;
    m_seek_time = seek_time;
}

